package test.ground;

import com.alibaba.fastjson.JSON;
import com.wang.tool.cache.aop.CacheKeyBuilder;
import com.wang.tool.cache.aop.EnableCache;
import com.wang.tool.executor.ExecutorFactory;
import com.wang.tool.executor.transitivethreadcontext.ThreadContextTransferTool;
import com.wang.tool.executor.transitivethreadcontext.ThreadContextTransmitter;
import com.wang.tool.extension.EnableExtension;
import com.wang.tool.hook.AppHook;
import com.wang.tool.hook.EnableAppHook;
import com.wang.tool.hook.SpringContextUtil;
import com.wang.tool.monitor.LinkLogUtil;
import com.wang.tool.monitor.aop.EnableMonitor;
import com.wang.tool.monitor.callback.MonitorCallback;
import com.wang.tool.monitor.core.LinkHolder;
import com.wang.tool.monitor.core.LinkInfo;
import com.wang.tool.monitor.core.LinkTransmitter;
import com.wang.tool.monitor.core.MonitorInfo;
import com.wang.tool.monitor.fastover.FastoverConfig;
import com.wang.tool.monitor.log.LogApi;
import com.wang.tool.monitor.log.LogInfo;
import com.wang.tool.monitor.ops.SimpleOps;
import com.wang.tool.monitor.weaver.MonitorWeaver;
import com.wang.tool.monitor.weaver.TypeWeaver;
import com.wang.tool.monitor.weaver.TypeWeaverFactory;
import com.wang.tool.monitor.writer.SimpleMonitorWriter;
import com.wang.tool.trace.EnableTrace;
import com.wang.tool.webtool.EnableWebTool;
import org.springframework.beans.BeansException;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.ApplicationContext;
import org.springframework.kafka.annotation.EnableKafka;
import org.springframework.scheduling.annotation.EnableAsync;
import test.ground.monitor.ServiceA;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.function.Consumer;

/**
 * @Author wangshaopeng
 * @Date 2020/12/28
 */
@SpringBootApplication
//web响应包装
@EnableWebTool
@EnableTrace
@EnableMonitor(callback = ToolApplication.MyCallback.class,monitorWriter = ToolApplication.W1.class,typeWeavers = {ToolApplication.MyTypeWeaver1.class, ToolApplication.MyTypeWeaver2.class, ToolApplication.MyTypeWeaver1.class},transmitter = ToolApplication.ContextTran.class)
@EnableAppHook(hooks = {ToolApplication.EI.class, SpringContextUtil.class})
@EnableExtension(
        scanPackages = {"test.ground.extension"}
)
@EnableCaching(order = -2)
@EnableCache(keyBuilder = ToolApplication.SimpleCacheKeyBuilder.class,dynamicListableOverAnnotation = true)
@EnableKafka
@EnableAsync(proxyTargetClass=true)
//@ImportResource("classpath:elastic-job.xml")
public class ToolApplication {


    public static void main(String[] args) {

        ThreadContextTransferTool.addGlobalTransmitter(new ThreadContextTransmitter() {
            @Override
            public Object get() {
                return LinkHolder.getCurrent();
            }

            @Override
            public void set(Object obj) {
                LinkHolder.setCurrent((LinkInfo) obj);
            }
        });

//        SpringApplication.addInitializers(new ApplicationContextInitializer<ConfigurableApplicationContext>() {
//            @Override
//            public void initialize(ConfigurableApplicationContext configurableApplicationContext) {
//
//            }
//        })



        SimpleOps.OpsSource source = new SimpleOps.OpsSource();
        SimpleOps.DetailConfig detailConfig = new SimpleOps.DetailConfig();
        detailConfig.setExpectStatus("遗产吗");
        detailConfig.setSpecialDetail(Arrays.asList("$.params[0]"));
        detailConfig.setSampleDetail(Arrays.asList("$.params"));
        detailConfig.setSampleRate(80);

        source.setDetailConfig(detailConfig);

        source.setSlowTime(10);
        source.setOutTime(100);
        SimpleOps.DebugConfig debugConfig = new SimpleOps.DebugConfig();
        debugConfig.setBeginHour("2023010112");
        debugConfig.setEndHour("2024010114");
        debugConfig.setSources(Arrays.asList("$[1]"));
        Set<String> objects = new HashSet<>();
        objects.add("1");
        objects.add("2");
        objects.add("3");

        debugConfig.setWhites(objects);


        source.setDebugConfig(debugConfig);
        FastoverConfig fastoverConfig = new FastoverConfig();
        fastoverConfig.setSources(Arrays.asList("$[1]"));
        fastoverConfig.setWhites(objects);
//        fastoverConfig.setFailover(new String[]{"1","2"});
        ServiceA.Result result = new ServiceA.Result("验证1");

        fastoverConfig.setFastReturn(new Object[]{ServiceA.Result.class.getName(), result});
        Date endTime = new Date();
        endTime.setHours(23);
//        fastoverConfig.setBeginTime(endTime);




        source.setFastoverConfig(fastoverConfig);
        System.out.println(JSON.toJSONString(source));


//        source.setFailover(new String[]{"错误码",null});
//        source.setDebugEval();
//        source.setObj();
//        source.setArray();
//        source.setSlowTimeEval();



//        source.setSnapshotEval();
//        source.setUnExpectSnapshotEval();
//        source.setExpectStatus();


//        MonitorOpsCenter.setOps(null,"ServiceA","hi", SimpleOps.parse(source));

        SimpleOps.OpsSource source2 = new SimpleOps.OpsSource();
        FastoverConfig fastoverConfig2 = new FastoverConfig();
//        fastoverConfig2.setSources(Arrays.asList("$[1]"));
//        fastoverConfig2.setWhites(objects);
//        fastoverConfig2.setFailover(new String[]{"1","2"});
        Object result2 = "3";

        fastoverConfig2.setFastReturn(new Object[]{"void", result2});
        source2.setFastoverConfig(fastoverConfig2);
//        SimpleOpsStorage.setOps("#MonitorC#t1", SimpleOps.parse(source2));


        TypeWeaverFactory.install(new TypeWeaver<String>() {
            @Override
            public Class<String> point() {
                return String.class;
            }

            @Override
            public void weaver(MonitorInfo<String> monitorInfo) throws Throwable {

            }
        });
        TypeWeaverFactory.install(new TypeWeaver<ServiceA.Result>() {
            @Override
            public Class<ServiceA.Result> point() {
                return ServiceA.Result.class;
            }

            @Override
            public void weaver(MonitorInfo<ServiceA.Result> monitorInfo) throws Throwable {
                ServiceA.Result result = monitorInfo.getResult();
                if (result!=null && !result.isSuccess()) {
                    monitorInfo.setStatus(result.getErrorStatus());
                }
            }
        });
//
        SpringApplication.run(ToolApplication.class);
    }

    public static class W1 extends SimpleMonitorWriter {


        @Override
        public void write(MonitorInfo<?> monitorInfo) {
            super.write(monitorInfo);
//            LinkLogUtil.newLinkLog(monitorInfo.getLink()).log();
            if (monitorInfo.isRoot()) {
                LinkLogUtil.newProfilerLog(monitorInfo.getLink()).log();
            }
//            if(monitorInfo.getGroup().equals("okhttp_template") && monitorInfo.getAction().equals("localhost:70/getRefresh")){
//                                LinkLogUtil.newProfilerLog(monitorInfo.getLink()).log();
//            }else if(monitorInfo.getGroup().equals("cache_get_or_refresh") && monitorInfo.getAction().equals("def")){
//                LinkLogUtil.newProfilerLog(monitorInfo.getLink()).log();
//            }else if(monitorInfo.getGroup().equals("redis") && monitorInfo.getAction().equals("get")){
//                LinkLogUtil.newProfilerLog(monitorInfo.getLink()).log();
//            }
        }
    }



    public static void inject(MonitorInfo monitorInfo){

//        monitorInfo.addDigest("tet1", new Random(100).nextInt());
//        monitorInfo.addDigest("tet1", new Random(100).nextInt());
//        monitorInfo.addDigest("tet1", new Random(100).nextInt());
//        monitorInfo.addDigest("tet1", new Random(100).nextInt());
//        monitorInfo.judgeNeedDetail();
//        monitorInfo.addPayloadJsonParams();
//        monitorInfo.addPayloadJsonResult();
    }

    public static class DW implements MonitorWeaver {

        @Override
        public void weaveOnBefore(MonitorInfo monitorInfo) {
            System.out.println(1111);

        }

        @Override
        public void weaveOnAfter(MonitorInfo monitorInfo) {

            System.out.println(2222);
        }
    }

    public static class EI implements AppHook {

        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
            System.out.println("chushihua 11111");
            ExecutorService executorService = Executors.newFixedThreadPool(1);
            ExecutorFactory.register("234", (ThreadPoolExecutor) executorService,executorService);
        }
    }



    public static class MyLogApi implements LogApi{
        @Override
        public Consumer<LogInfo> getLogger(String loggerName, LinkInfo linkInfo) {
            return null;
        }

        @Override
        public void error(Throwable e, String errorCode, LogInfo logInfo) {

        }
    }




    public static class ContextTran implements LinkTransmitter {
        private static Map<Long, LinkInfo> cache = new ConcurrentHashMap<>();





        @Override
        public LinkInfo get() {
            return cache.get(Thread.currentThread().getId());
        }

        @Override
        public void set(LinkInfo linkInfo) {
            if (linkInfo==null) {
                cache.remove(Thread.currentThread().getId());
            }else{
                cache.put(Thread.currentThread().getId(), linkInfo);
            }
        }
    }



    public static class MyCallback implements MonitorCallback {


        @Override
        public void beforeWrite(MonitorInfo<?> monitorInfo) {
//            System.out.println("我是插件");
        }
    }


    public static class MyTypeWeaver2 implements TypeWeaver<ServiceA.Result2> {

        @Override
        public Class<ServiceA.Result2> point() {
            return ServiceA.Result2.class;
        }

        @Override
        public void weaver(MonitorInfo<ServiceA.Result2> monitorInfo) throws Throwable {
//            System.out.println("我是类型编织");
        }
    }


    public static class MyTypeWeaver1 implements TypeWeaver<ServiceA.Result> {

        @Override
        public Class<ServiceA.Result> point() {
            return ServiceA.Result.class;
        }

        @Override
        public void weaver(MonitorInfo<ServiceA.Result> monitorInfo) throws Throwable {
//            System.out.println("我是类型编织1");
        }
    }


    public static class SimpleCacheKeyBuilder implements CacheKeyBuilder{
        @Override
        public String build(String instance, String namespace, String express, Object[] params) {
            StringBuilder xx = new StringBuilder();
            for (Object param : params) {
                xx.append(param);
            }
            return xx.toString();
        }
    }

}
